<?php

namespace frontend\filters;

use Yii;
use yii\filters\auth\HttpBearerAuth;
use common\helpers\ArrayHelper;
use common\models\app\AppToken;

/**
 * HttpBearerAuth is an action filter that supports the authentication method based on HTTP Bearer token.
 *
 * @author emhome <emhome@163.com>
 * @since 1.0
 */
class AppBearerAuth extends HttpBearerAuth {

    /**
     * @var integer current user identify id.
     */
    public $uid = 0;

    /**
     * @var AppToken|null the HTTP authentication token
     */
    public $token = null;

    /**
     * @var string the HTTP authentication realm
     */
    public $realm = 'api';

    /**
     * @var string the HTTP authentication realm
     */
    public $closeCheckAuthent = true;

    /**
     * @inheritdoc
     */
    public function beforeAction($action) {
        /* @var $request \yii\web\Request */
        $request = $this->request ?: Yii::$app->getRequest();
        $response = $this->response ?: Yii::$app->getResponse();
        if ($this->closeCheckAuthent === true) {
            return true;
        }
        if ($request->isOptions) {
            $allowOrigins = ArrayHelper::getValue(Yii::$app->params, 'crossDomains', []);
            if (!$request->origin || in_array($request->origin, $allowOrigins)) {
                return true;
            }
            return false;
        }
        $token = new AppToken();
        $identity = $this->authenticate($token, $request, $response);
        if ($identity !== null) {
            $uid = $identity->user_id;
            $user = $uid ? $identity->user : null;
            if ($user) {
                Yii::$app->user->login($user);
            }
            $this->uid = $uid;
            $this->token = $identity;
            $this->bindVersion($response);
            return true;
        }
        $this->challenge($response);
        $this->handleFailure($response);
        return false;
    }

    /**
     * @param \common\models\app\AppToken $user
     * @param \yii\web\Request $request
     * @inheritdoc
     */
    public function authenticate($user, $request, $response) {
        $authHeader = $request->getHeaders()->get('Authorization');
        if ($authHeader !== null && preg_match("/^Bearer\\s+(.*?)$/", $authHeader, $matches)) {
            return $user->loginByAccessToken($matches[1], get_class($this));
        } else {
//            if (YII_ENV_DEV) {
//                $identity = AppToken::findOne(1);
//                if ($identity === null) {
//                    $this->handleFailure($response);
//                }
//                return $identity;
//            }
        }
        return null;
    }

    /**
     * @inheritdoc
     */
    public function challenge($response) {
        $response->getHeaders()->set('WWW-Authenticate', "Bearer realm=\"{$this->realm}\"");
    }

    /**
     * @inheritdoc
     */
    public function bindVersion($response) {
        $response->getHeaders()->set('Access-Control-Expose-Headers', "Build");
        $response->getHeaders()->set('Build', $this->token->build);
    }

}
